package xyz.scootaloo.kami.server.verticle

import io.vertx.core.http.HttpServer
import io.vertx.ext.web.Router
import io.vertx.kotlin.coroutines.await
import org.ktorm.database.Database
import xyz.scootaloo.kami.server.controller.BaseController
import xyz.scootaloo.kami.server.standard.getLogger
import xyz.scootaloo.kami.server.service.AppConfig
import xyz.scootaloo.kami.server.service.StageEventEmitter

/**
 * @author flutterdash@qq.com
 * @since 2022/3/17 21:11
 */

fun liteComponents() = listOf(
    HttpServerComponent,
    DatabaseComponent
)

object HttpServerComponent : LiteComponent {
    private lateinit var httpServer: HttpServer

    override val isWorker = false
    override val componentName = "http-server"

    override suspend fun deploy(config: AppConfig): String {
        val serverConfig = config.serverConfig
        val serverPort = serverConfig.port
        httpServer = vertx.createHttpServer()
        bindRequestHandlers()
        httpServer.listen(serverPort).await()
        return "监听端口[$serverPort]"
    }

    override suspend fun undeploy(): String? {
        httpServer.close().await()
        return null
    }

    private fun bindRequestHandlers() {
        val rootRouter = Router.router(vertx)
        BaseController.bindRouters(vertx, rootRouter)
        httpServer.requestHandler(rootRouter)
    }
}

object DatabaseComponent : LiteComponent {
    private val log by lazy { getLogger() }

    override val isWorker = true
    override val componentName = "database-server"

    override suspend fun deploy(config: AppConfig): String {
        val dbConfig = config.databaseConfig
        val dbPath = dbConfig.path
        val exists = vertx.fileSystem().exists(dbPath).await()
        if (!exists) {
            log.error("数据库文件未找到: `${dbPath}`")
            throw RuntimeException("数据库未找到")
        }
        setGlobalDatabaseRef(
            Database.connect(
            driver = "org.sqlite.JDBC",
            url = "jdbc:sqlite:${dbPath}"
        ))
        StageEventEmitter.afterDatabaseAvailable()
        return "使用数据库文件[`$dbPath`]"
    }

    override suspend fun undeploy(): String? {
        return null
    }
}